use proc_macro::{TokenStream};
use syn::{parse_macro_input, FnArg, ItemFn, Pat, Type};
use quote::quote;

pub fn do_inspect_args(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // 解析输入的函数
    let input_fn = parse_macro_input!(item as ItemFn);
    let sig = &input_fn.sig;
    let fn_name = &sig.ident;

    // 获取参数信息
    let params = &sig.inputs;
    let mut param_types = Vec::new();
    let mut param_names = Vec::new();

    for param in params {
        match param {
            FnArg::Typed(pat_type) => {
                // 获取参数类型
                let ty = &pat_type.ty;
                param_types.push(ty);

                // 获取参数名称
                if let Pat::Ident(ident) = &*pat_type.pat {
                    param_names.push(&ident.ident);
                }
            }
            FnArg::Receiver(_) => {
                // 忽略self参数
            }
        }
    }

    // 生成新函数名
    let inspector_name = syn::Ident::new(&format!("{}_inspector", fn_name), fn_name.span());

    let fn_name_str = fn_name.to_string();
    let param_len = param_types.len();

    // 生成代码
    let expanded = quote! {
        #input_fn

        pub fn #inspector_name() {
            info!("Function {} has {} parameters:", #fn_name_str, #param_len);

            #(
                info!("- {}: {}", stringify!(#param_names), stringify!(#param_types));
            )*
        }

        pub struct #inspector_name {
            pub t: String,
        }
    };

    TokenStream::from(expanded)
}


pub fn do_intercept_method(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input_fn = parse_macro_input!(item as ItemFn);
    let sig = &input_fn.sig;
    // let vis = &input_fn.vis;
    // let block = &input_fn.block;
    let function_name = &sig.ident;
    let inputs = &input_fn.sig.inputs;
    let result_type = &input_fn.sig.output;

    let mut test_inputs = Vec::new();
    let mut test_params = Vec::new();
    for arg in sig.inputs.iter() {
        if let FnArg::Typed(pat_type) = arg {
            if let Pat::Ident(pat_ident) = &*pat_type.pat {
                let arg_name = &pat_ident.ident;
                // 根据参数类型生成测试值
                match &*pat_type.ty {
                    Type::Path(type_path) => {
                        if let Some(seg) = type_path.path.segments.last() {
                            let arg_type = seg.ident.to_string();
                            test_inputs.push(quote! { #arg_name: #arg_type });
                            test_params.push(quote! { #arg_name });
                        } else {
                            ()
                        }
                    }
                    _ => ()
                };

            }
        }
    }

    let new_function_name = format!("{}_new", function_name.clone());
    let expanded = quote! {
        #input_fn

        fn add_new(#inputs) #result_type {
            let start = std::time::Instant::now();
            let result = #function_name(#(#test_params, )*);
            info!("{} 2333 took {:?}", stringify!(#function_name), start.elapsed());
            result
        }

        pub fn tests() {
            info!("new Function {}, {}", #new_function_name, stringify!(#result_type));
        }
    };
    expanded.into()
}